package cn.xyt.service;

import java.lang.reflect.Method;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import cn.tom.db.jdbc.Query;
import cn.tom.db.jdbc.simple.DBQuery;
import cn.tom.db.jdbc.simple.DBUtil;
import cn.tom.kit.StringUtil;
import cn.tom.kit.clazz.ReflectUtil;
import cn.tom.protocol.http.HttpMessage;
import cn.tom.protocol.http.HttpMessage.Meta;
import cn.tom.transport.Session;
import cn.xyt.dto.SystemProperty;
import cn.xyt.util.DeviceCache;
import cn.xyt.util.HttpUtil;
import cn.xyt.util.JPushUtil;
import cn.xyt.util.PullSession;

/**
 * http://127.0.0.1:7070/sendcmd?cmd=11&deviceid=123456&code=2,1
 * @author tomsun
 *
 */
@Service
public class RpcService extends BaseService {

	@Resource
	SystemProperty systemProperty;

	private Map<String, Method> methods = new HashMap<>();

	public RpcService() throws NoSuchMethodException, SecurityException {
		Class<?> clazz = this.getClass();

		methods.put("deviceinfo", clazz.getDeclaredMethod("deviceinfo", HttpMessage.class, Session.class));
		methods.put("gpsinfo", clazz.getDeclaredMethod("gpsinfo", HttpMessage.class, Session.class));
		methods.put("deviceset", clazz.getDeclaredMethod("deviceset", HttpMessage.class, Session.class));
		methods.put("execsql", clazz.getDeclaredMethod("execsql", HttpMessage.class, Session.class));
		methods.put("querysql", clazz.getDeclaredMethod("querysql", HttpMessage.class, Session.class));
		methods.put("queryone", clazz.getDeclaredMethod("queryone", HttpMessage.class, Session.class));
		methods.put("declareTopic", clazz.getDeclaredMethod("declareTopic", HttpMessage.class, Session.class));
	
	}

	/**
	 * 设备信息 可以批量
	 * @param msg
	 * @return
	 */
	public Map<String, Object> deviceinfo(HttpMessage msg, Session sess) {
		String _dids = msg.getMeta().getParam("dids");
		if (!StringUtil.hasLength(_dids))
			return correct("", Collections.EMPTY_LIST);

		String[] dids = _dids.split(",");
		StringBuffer values = new StringBuffer();
		for (String did : dids) {
			if (values.length() > 0) {
				values.append(",");
			}
			values.append("(").append(did).append(")");
		}
		Query query = new DBQuery(
				"select a.did,last_percent, last_mileage, total_milleage, curr_milleage, a.lat, a.lon from gpsone a join battery b on a.did = b.did where a.did ");
		query.add("= ANY(VALUES" + values + ")");
		List<Map<String, Object>> list = DBUtil.getList(query.getSql());
		for (Map<String, Object> map : list) {
			String did = String.valueOf(map.get("did")) ;
			if (DeviceCache.asMap().containsKey(did))
				map.put("isonline", true);
			else
				map.put("isonline", false);
		}
		return correct("", list);
	}

	public Map<String, Object> gpsinfo(HttpMessage msg, Session sess) {
		Meta meta = msg.getMeta();
		Query query = new DBQuery("SELECT lon, lat FROM gpslog").where("1=1");
		query.and("did = ?").setParams(Long.parseLong(meta.getParam("did")));
		query.and("ctime::date = ?").setParams(Date.valueOf(meta.getParam("ctime")));
		query.asc("ctime");
		List<Map<String, Object>> list = DBUtil.getList(query.getSql(), query.getParams());
		List<Object[]> ll = new ArrayList<>();
		for(Map<String, Object> map: list){
			ll.add(new Object[]{map.get("lon"), map.get("lat")});
		}
		return correct("", ll);
	}

	/**
	 * 初始化 deviceset信息
	 * @param msg
	 * @return
	 */
	public Map<String, Object> execsql(HttpMessage msg, Session sess) {
		Meta meta = msg.getMeta();
		String sql = meta.getParam("sql");
		String params = msg.getBodyString("UTF-8");
		List<Object> execParams = HttpUtil.paserArray(params.isEmpty()? "[]" :params);
		int i = DBUtil.exec(sql, execParams.toArray());
		if(i>0){
			return correct("执行成功");
		}
		return correct("执行失败");
	}
	
	/**
	 * queryList 接口
	 * @param msg
	 * @return
	 */
	public Map<String, Object> querysql(HttpMessage msg, Session sess) {
		Meta meta = msg.getMeta();
		String sql = meta.getParam("sql");
		String params = msg.getBodyString("UTF-8");
		List<Object> execParams = HttpUtil.paserArray(params.isEmpty()? "[]" :params);
		List<Map<String, Object>> result =  DBUtil.getList(sql, execParams.toArray());
		return correct("查询结果集", result);
	}
	
	
	public Map<String, Object> queryone(HttpMessage msg, Session sess) {
		Meta meta = msg.getMeta();
		String sql = meta.getParam("sql");
		String params = msg.getBodyString("UTF-8");
		List<Object> execParams = HttpUtil.paserArray(params.isEmpty()? "[]" :params);
		Map<String, Object> result =  DBUtil.getMap(sql, execParams.toArray());
		return correct("查询结果集", result);
	}
	

	public Map<String, Object> declareTopic(HttpMessage msg, Session sess) {
		// 保存拉取的 session 和 msg[便于返回]
		JPushUtil.pullMap.put(msg.getHead("topic"), new PullSession(sess, msg));
		System.out.println("====订阅成功====" +msg);
		return correct("订阅成功");
	}
	
	
	public Map<String, Object> deviceset(HttpMessage msg, Session sess) {
		Meta meta = msg.getMeta();
		Long did = Long.parseLong(meta.getParam("did"));
		String bleid = meta.getParam("bleid");
		Integer volt = Integer.parseInt(meta.getParam("volt"));
		Integer ah = Integer.parseInt(meta.getParam("ah"));
		Integer max_speed = Integer.parseInt(meta.getParam("max_speed"));
		String sql = "SELECT 1 FROM deviceset WHERE deviceid = ?";
		List<Map<String, Object>> list = DBUtil.getList(sql, did);
		if (list.isEmpty())
			sql = "INSERT INTO deviceset (uid, bleid, volt, ah, max_speed, deviceid)" + "VALUES(0, ?, ?, ?, ?,  ?)";
		else
			sql = "UPDATE deviceset SET bleid = ?, volt = ?, ah = ?, max_speed = ? WHERE deviceid = ?";
		DBUtil.exec(sql, bleid, volt, ah, max_speed, did);
		return correct("设置成功。");
	}

	public HttpMessage invoke(HttpMessage msg, Session session) {
		String module = msg.getParam("module");
		Method method = methods.get(module);

		HttpMessage res = msg;
		Map<String, Object> map = null;
		try {
			map = (Map<String, Object>) ReflectUtil.invokeMethod(this, method, msg, session);
			if(map == null)	 return null;
			res.setStatus("200");
		} catch (Exception e) {
			logger.error("RpcService.invoke:: " + module, e);
			map = error(e.getMessage());
			res.setStatus("500");
		}
		res.setJsonBody(HttpUtil.serialize(map));

		return res;
	}

	public static void main(String[] args) {
		String[] dids = "1,2,3,4,5".split(",");
		StringBuffer bu = new StringBuffer();
		for (String did : dids) {
			if (bu.length() > 0) {
				bu.append(",");
			}
			bu.append("(").append(did).append(")");
		}
		Query query = new DBQuery(
				"select a.did,last_percent, last_mileage, a.lat, a.lon from gpsone a join battery b on a.did = b.did where a.did ");
		query.add("= ANY(VALUES" + bu + ")");
		System.out.println(query.getSql());

	}

}
